/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package AlignmentHelper;

import ParTreeVisualizer.SentenceAlignement;
import ParTreeVisualizer.WordAlignement;
import ibmmodel3.*;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;

/**
 *
 * @author mwh
 */
public class IO {

    public static void writeGIZA(List<GIZAAlignment> a, String filename) throws IOException {

        int an = 0;

        PrintWriter out = new PrintWriter(new FileWriter(filename));

        for (GIZAAlignment ga : a) {
            writeGIZA(ga, out, an++);
        }

        out.close();

    }


    private static void writeGIZA(GIZAAlignment a, PrintWriter out, int an) {

        out.write("Sentece pair (" + an + ")\n");
        for (String w : a.ss2) {
            out.write(w + " ");
        }
        out.write("\n");
        out.write("NULL ({");
        Set<Integer> aligns = a.a.get(0);
        for (Integer aln : aligns) {
            out.write(aln + " ");
        }
        out.write("}) ");

        for (int i = 0; i < a.ss1.size(); i++) {
            String w = a.ss1.get(i);
            aligns = a.a.get(i + 1);
            out.write(w + " ");
            out.write("({ ");
            for (Integer aln : aligns) {
                out.write(aln + " ");
            }
            out.write("}) ");
        }
        out.write("\n");
    }


    public static void writeUPlugXML(List<SentenceAlignement> sal, String filename) throws ParserConfigurationException, TransformerConfigurationException, FileNotFoundException, TransformerException, IOException {

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document doc = builder.newDocument();

        String fnS = filename + ".lang1.xml";
        String fnT = filename + ".lang2.xml";


        writeUPlugText(sal, fnS, fnT);

        Element rootElement = doc.createElement("CESAlign");
        Element linkGrp = doc.createElement("linkGrp");
        linkGrp.setAttribute("targType", "s");
        linkGrp.setAttribute("toDoc", fnS);
        linkGrp.setAttribute("fromDoc", fnT);

        rootElement.setAttribute("version", "1.1");
        doc.appendChild(rootElement);
        rootElement.appendChild(linkGrp);
        int pn = 1;
        int sn = 1;
        int an = 0;
        for (SentenceAlignement sa : sal) {
            Element link = doc.createElement("link");
            link.setAttribute("xtargets", "s" + pn + "." + sn + ";" + "s" + pn + "." + sn);
            rootElement.appendChild(link);


            for (WordAlignement wa : sa.a) {

                String xTarget1 = "";
                String xTarget2 = "";
                String lexPair1 = "";
                String lexPair2 = "";

                boolean first1 = true;
                boolean first2 = true;

                for (Integer w : wa.w1) {
                    if (first1) {
                        first1 = false;
                    } else {
                        xTarget1 = xTarget1 + "+";
                        lexPair1 = lexPair1 + " ";
                    }
                    int wp = w + 1;
                    xTarget1 = xTarget1 + "w" + pn + "." + sn + "." + wp;
                    lexPair1 = lexPair1 + sa.s1.get(w);
                }
                for (Integer w : wa.w2) {
                    if (first2) {
                        first2 = false;
                    } else {
                        xTarget2 = xTarget2 + "+";
                        lexPair2 = lexPair2 + " ";
                    }
                    int wp = w + 1;
                    xTarget2 = xTarget2 + "w" + pn + "." + sn + "." + wp;
                    lexPair2 = lexPair2 + sa.s2.get(w);
                }
                Element wordLink = doc.createElement("wordLink");
                wordLink.setAttribute("xtargets", xTarget2 + ";" + xTarget1);
                wordLink.setAttribute("lexPair", lexPair2 + ";" + lexPair1);
                link.appendChild(wordLink);

            }

            pn++;

            an++;
        }



        Transformer t = TransformerFactory.newInstance().newTransformer();
        t.setOutputProperty(OutputKeys.INDENT, "yes");
        t.transform(new DOMSource(doc), new StreamResult(new FileOutputStream(filename + ".xml")));


    }


    private static void writeUPlugText(List<SentenceAlignement> sal, String fn1, String fn2) throws ParserConfigurationException, TransformerConfigurationException, FileNotFoundException, TransformerException, IOException {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder1 = factory.newDocumentBuilder();
        DocumentBuilder builder2 = factory.newDocumentBuilder();
        Document doc1 = builder1.newDocument();
        Document doc2 = builder2.newDocument();

        Element rootElement1 = doc1.createElement("text");
        doc1.appendChild(rootElement1);
        Element rootElement2 = doc2.createElement("text");
        doc2.appendChild(rootElement2);
        int p1 = 1;
        int p2 = 1;

        for (SentenceAlignement sa : sal) {


            Element par1 = doc1.createElement("p");
            Element par2 = doc2.createElement("p");
            par1.setAttribute("id", "" + p1);
            par2.setAttribute("id", "" + p2);
            rootElement1.appendChild(par1);
            rootElement2.appendChild(par2);
            int s1 = 1;
            int s2 = 1;
            Element sen1 = doc1.createElement("s");
            Element sen2 = doc2.createElement("s");
            sen1.setAttribute("id", "s" + p1 + "." + s1);
            sen2.setAttribute("id", "s" + p2 + "." + s2);
            par1.appendChild(sen1);
            par2.appendChild(sen2);

            int w1 = 1;

            for (String w : sa.s1) {
                Element word1 = doc1.createElement("w");
                word1.setAttribute("id", "w" + p1 + "." + s1 + "." + w1);
                Text text1 = doc1.createTextNode(w);
                word1.appendChild(text1);
                sen1.appendChild(word1);
                w1++;
            }
            int w2 = 1;
            for (String w : sa.s2) {
                Element word2 = doc2.createElement("w");
                word2.setAttribute("id", "w" + p2 + "." + s2 + "." + w2);
                Text text2 = doc2.createTextNode(w);
                word2.appendChild(text2);
                sen2.appendChild(word2);
                w1++;
            }


            p1++;
            p2++;
        }


        Transformer t = TransformerFactory.newInstance().newTransformer();
        t.setOutputProperty(OutputKeys.INDENT, "yes");

        t.transform(new DOMSource(doc1), new StreamResult(new FileOutputStream(fn1)));
        t.transform(new DOMSource(doc2), new StreamResult(new FileOutputStream(fn2)));


    }


    public static List<SentenceAlignement> readATAG(String filename) throws FileNotFoundException, IOException {
        List<SentenceAlignement> alignments = new ArrayList<SentenceAlignement>();

        String fn1 = "";
        String fn2 = "";

        BufferedReader input = new BufferedReader(new FileReader(filename));

        String line;
        line = input.readLine();

        if (!line.equals("<DTAGalign>")) {
            System.err.println("Not a DTAG-align file");
            return alignments;
        }
        line = input.readLine();
        // <alignFile key="a" href="0021-dk.tag" sign="_input"/>
        Pattern pattern = Pattern.compile(".*href=\"(.*?)\".*");
        Matcher ma = pattern.matcher(line);
        if (ma.matches()) {
            fn1 = ma.group(1);
        }

        line = input.readLine();
        ma = pattern.matcher(line);
        if (ma.matches()) {
            fn2 = ma.group(1);
        }
        System.err.println(fn1 + " " + fn2);


        Map<Integer, Integer> ln2sen1 = new HashMap<Integer, Integer>();
        Map<Integer, Integer> ln2sen2 = new HashMap<Integer, Integer>();
        Map<Integer, Integer> senstart1 = new HashMap<Integer, Integer>();
        Map<Integer, Integer> senstart2 = new HashMap<Integer, Integer>();


        List<List<String>> sen1 = readTAG(fn1, ln2sen1, senstart1);
        List<List<String>> sen2 = readTAG(fn2, ln2sen2, senstart2);


        // <align out="a43" type="" in="b1" creator="-1" insign="2" outsign="2"/>
        pattern = Pattern.compile("<align out=\"([\\w\\s]+)\".*in=\"([\\w\\s]+)\".*insign=\"(.*?)\".*outsign=\"(.*?)\".*");

        List<List<WordAlignement>> was = new ArrayList<List<WordAlignement>>();
        for (int i = 0; i < sen1.size(); i++) {
            was.add(new ArrayList<WordAlignement>());
        }

        Pattern pattern2 = Pattern.compile("(\\w)(\\d+)");
        Matcher ma2;
        while ((line = input.readLine()) != null) {
            ma = pattern.matcher(line);
            if (ma.matches()) {
                String out = ma.group(1);
                String in = ma.group(2);


                // Skip all alignements of ends and beginnings of sentences
                if (!(ma.group(3).equals("<s>") || ma.group(3).equals("</s>") || ma.group(4).equals("<s>") || ma.group(4).equals("</s>"))) {
                    String[] outs = out.split(" ");
                    String[] ins = in.split(" ");
                    Set<Integer> wordsSen1 = new HashSet<Integer>();
                    Set<Integer> wordsSen2 = new HashSet<Integer>();
                    int sn = -1;
                    for (String o : outs) {
                        ma2 = pattern2.matcher(o);
                        if (ma2.matches()) {
                            String senid = ma2.group(1);
                            int ln = Integer.parseInt(ma2.group(2));
//                            System.err.println("LIN " + senid + "  " + ln);
//                            System.err.println(line);

                            int ss = -1;
                            if (senid.equals("a")) {
                                sn = ln2sen1.get(ln);
                                ss = senstart1.get(sn);
                                wordsSen1.add(ln - ss);
                            }
                            if (senid.equals("b")) {
//                                System.err.println(ln);
//                                System.err.println(ln2sen2);

                                sn = ln2sen2.get(ln);
                                ss = senstart2.get(sn);
                                wordsSen2.add(ln - ss);
                            }
                        }
                    }
                    for (String i : ins) {
                        ma2 = pattern2.matcher(i);
                        if (ma2.matches()) {
                            String senid = ma2.group(1);
                            int ln = Integer.parseInt(ma2.group(2));
                            //                          System.err.println("LIN " + senid + "  " + ln);
                            //        System.err.println(line);

                            int ss = -1;
                            if (senid.equals("a")) {
                                sn = ln2sen1.get(ln);
                                ss = senstart1.get(sn);
                                wordsSen1.add(ln - ss);
                            }
                            if (senid.equals("b")) {

//System.err.println(ln2sen2);
                                sn = ln2sen2.get(ln);
                                ss = senstart2.get(sn);
                                wordsSen2.add(ln - ss);
                            }

                        }
                    }
//                    System.err.println(Arrays.toString(ins) + " + " + Arrays.toString(outs));
//                    System.err.println("sen1: " + wordsSen1);
//                    System.err.println("sen2: " + wordsSen2);
                    if (!(wordsSen1.isEmpty() || wordsSen2.isEmpty())) {
                        WordAlignement wa = new WordAlignement(wordsSen1, wordsSen2);
                        was.get(sn - 1).add(wa);
                    }

                }

            }
        }
//        System.err.println(sen1);
//        System.err.println(sen2);

        for (int i = 0; i < sen1.size(); i++) {
            List<String> s1 = sen1.get(i);
            List<String> s2 = sen2.get(i);

            SentenceAlignement sa = new SentenceAlignement(s1, s2, was.get(i));
            alignments.add(sa);
        }
        return alignments;
    }


    private static List<List<String>> readTAG(String fn, Map<Integer, Integer> ln2sen, Map<Integer, Integer> senstart) throws FileNotFoundException, IOException {
        fn = "/home/mwh/DGS/cdt/da-en/" + fn;
        BufferedReader input = new BufferedReader(new FileReader(fn));

        List<List<String>> res = new ArrayList<List<String>>();
        List<String> cur = new ArrayList<String>();
        String line;
        int sn = 0;
        int ln = 0;
        // <W msd="CD" in="" out="1:pnct|7:list|15:pnct">2</W>
        Pattern pattern = Pattern.compile("<W.*?>(.*?)</W>");
        Matcher ma;
        while ((line = input.readLine()) != null) {
//            System.err.println(ln + "  "+ line);
            if (line.equals("<s>")) {
                sn++;
                senstart.put(sn, ln + 1);
                cur = new ArrayList<String>();
                res.add(cur);
            } else {

                ma = pattern.matcher(line);
                if (ma.matches()) {
//                    System.err.println("mmm  " + ln);
                    String word = ma.group(1);

                    cur.add(word);

                    ln2sen.put(ln, sn);
                }
            }

            ln++;


        }

//        System.err.println(ln2sen);
//        System.err.println(senstart);
//        System.err.println(res);
        return res;
    }


    public static List<List<String>> readACLText(String fn) throws FileNotFoundException, IOException {

        List<List<String>> res = new ArrayList<List<String>>();

        BufferedReader input = new BufferedReader(new FileReader(fn));

        Pattern pattern = Pattern.compile("<s snum=(\\d+)> (.*)</s>");
        Matcher ma;

        String line;

        while ((line = input.readLine()) != null) {
            //line = line.toLowerCase();
            ma = pattern.matcher(line);
            if (ma.matches()) {
       //         System.err.println(ma.group(1) + ": " + ma.group(2));
                String[] sena = ma.group(2).split(" ");
                List<String> sen = Arrays.asList(sena);
                int sn = Integer.parseInt(ma.group(1));
                while (sn >= res.size()) {
                    res.add(new ArrayList<String>());
                }
                res.set(sn, sen);
            }
        }

        return res;

    }


    public static List<SentenceAlignement> readACLAlignment(String fn, List<List<String>> ssen, List<List<String>> tsen) throws FileNotFoundException, IOException {

        List<SentenceAlignement> res = new ArrayList<SentenceAlignement>();
        BufferedReader input = new BufferedReader(new FileReader(fn));

        String line;
        Map<Integer, Integer> sennr2listindex = new HashMap<Integer, Integer>();

        while ((line = input.readLine()) != null) {
            String[] tok = line.split(" ");
            int sn = Integer.parseInt(tok[0]);
            int sa = Integer.parseInt(tok[1]) - 1;
            int ta = Integer.parseInt(tok[2]) - 1;
            SentenceAlignement sena;
            if (sennr2listindex.containsKey(sn)) {
                sena = res.get(sennr2listindex.get(sn));
            } else {
                sena = new SentenceAlignement(ssen.get(sn), tsen.get(sn), new ArrayList<WordAlignement>());
                sennr2listindex.put(sn, res.size());
                res.add(sena);

            }
            List<WordAlignement> wal = sena.a;
            boolean added = false;
            for (WordAlignement wa : wal) {
                if (wa.w1.contains(sa)) {
                    wa.w2.add(ta);
                    added = true;

                }
                if (wa.w2.contains(ta)) {
                    wa.w1.add(sa);
                    added = true;
                }
            }
            if (!added) {

                Set<Integer> sset = new HashSet<Integer>();
                Set<Integer> tset = new HashSet<Integer>();
                sset.add(sa);
                tset.add(ta);
                wal.add(new WordAlignement(sset, tset));

            }


        }

        return res;
    }


    public static void writeACLAlignment(List<SentenceAlignement> sal, String fn) throws IOException {

        PrintWriter slang = new PrintWriter(new FileWriter(fn + ".acl.slang"));
        PrintWriter tlang = new PrintWriter(new FileWriter(fn + ".acl.tlang"));
        PrintWriter alig = new PrintWriter(new FileWriter(fn + ".acl.alig"));



        int sn = 1;
        for (SentenceAlignement sa : sal) {

            slang.print("<s snum=" + sn + "> ");
            for (String s : sa.s1) {
                slang.print(s + " ");
            }
            slang.println("</s>");

            tlang.print("<s snum=" + sn + "> ");
            for (String s : sa.s2) {
                tlang.print(s + " ");
            }
            tlang.println("</s>");

            for (WordAlignement wa : sa.a) {

                for (Integer s : wa.w1) {

                    int s1 = s + 1;
             //       System.err.println("  " + s1);
                    for (Integer t : wa.w2) {

                        int t1 = t + 1;
               //         System.err.println("      " + t1);
                        alig.println(sn + " " + s1 + " " + t1);
                    }
                }
            }

            sn++;
        }

        slang.close();
        tlang.close();
        alig.close();

    }
}
